package tss;

import java.io.*;

/**
 * A Layer represents a part of a protocol stack
 * 
 * Layers are (possibly) connected with a layer above
 * it and a layer below it. 
 * 
 * It communicates with these layers only through its up
 * and down methods 
 * 
 * @author Klaus Marius Hansen, klaus.m.hansen@daimi.au.dk
 *
 */
public abstract class Layer {
	private Layer above, below;
	/**
	 * The id of the process that this layer is instantiated in
	 */
	protected int id; 
	private String[] properties;
	
	/**
	 * Set the properties of this layer. It is expected
	 * that at least "process.id" is set for all layers
	 * 
	 * @param properties : a set of strings "key1", "value1", ..., "keyN", "valueN"
	 * @throws IllegalArgumentException if properties is not of even length
	 */
	public void setProperties(String ... properties) throws IllegalArgumentException  {
		this.properties = properties;
		if (properties.length%2 != 0) {
			throw new IllegalArgumentException("Layer properties length should be an even number");
		}
		id = (getProperty("process.id") != null) ? new Integer(getProperty("process.id")) : -1 ;
	}
	
	/**
	 * Return the value of a property 
	 * 
	 * @param key : the property key to find a value for
	 * 
	 * @return the value that was matched with key in setProperties or null if
	 *         it was not set
	 */
	public String getProperty(String key) {
		String result = null;
		if (properties != null) {
			for (int i = 0; i < properties.length; i = i + 2) {
				if (properties[i].equals(key)) {
					result = properties[i + 1];
				}
			}
		}
		return result;
	}
	
	/**
	 * Set the lower layer for this layer
	 * 
	 * @param above : the layer above 
	 */
	public void setUpperLayer(Layer above) {
		this.above = above;
	}
	
	/**
	 * Set the lower layer for this layer

	 * @param below
	 */
	public void setLowerLayer(Layer below) {
		this.below = below;
	}
	
	/**
	 * Called from the layer above for this layer to handle a message
	 * 
	 * <p>Subclasses are expected to override this method
	 * 
	 * @param message : the message that is passed down through the layers
	 */
	public void down(Message message) throws IOException {
		if (below != null) {
			below.down(message);
		}
	}
	
	/**
	 * Called from the layer below for this layer to handle a message
	 * 
	 * <p>Subclasses are expected to override this method
	 * 
	 * @param message : the message that is passed up through the layers
	 */
	public void up(Message message)  {
		if (above != null) {
			above.up(message);
		}
	}
}
